﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Application.Entity;
using AngleSharp.Dom;
using DocumentFormat.OpenXml.Spreadsheet;
using Mapster;
using Newtonsoft.Json;
using NPOI.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WCS.Application.Entity.Warehous;
using WCS.Application.Service.Device;
using WCS.Application.Service.Maintenance;


namespace WCS.Application.Service.Device;
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 16)]
[AllowAnonymous]
public class DeviceService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<DeviceMaintenanceEntity> _device;

    private readonly UserManager _userinfo;

    // 修复 CS0501 错误：为构造函数提供主体  
    public DeviceService(SqlSugarRepository<DeviceMaintenanceEntity> device, UserManager userinfo)
    {
        _device = device;

        _userinfo = userinfo;

    }


    /// <summary>
    /// 获取设备分页列表
    /// </summary>
    [ApiDescriptionSettings(Name = "GetDevicePageList"), HttpPost]
    public async Task<SqlSugarPagedList<DeviceMaintenanceEntity>> GetDevicePageList([FromBody] DevicePageInputDto input)
    {

        var query = _device.AsQueryable().WhereIF(!string.IsNullOrWhiteSpace(input.DeviceId), u => u.DeviceId.Contains(input.DeviceId))
            .WhereIF(!string.IsNullOrWhiteSpace(input.DeviceType.ToString()), u => u.DeviceType == input.DeviceType.Value)
            .WhereIF(input.DeviceStatus.HasValue, u => u.DeviceStatus == input.DeviceStatus.Value)
        .OrderBuilder(input);

        return await query.ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 获取设备列表
    /// </summary>
    [ApiDescriptionSettings(Name = "GetDeviceList"), HttpPost]
    public async Task<List<DeviceMaintenanceEntity>> GetDeviceList([FromBody] DevicePageInputDto input)
    {
        var query = _device.AsQueryable();

        if (!string.IsNullOrWhiteSpace(input.DeviceId))
            query = query.Where(d => d.DeviceId.Contains(input.DeviceId));
        if (input.DeviceType.HasValue)
            query = query.Where(d => d.DeviceType == input.DeviceType.Value);
        if (input.DeviceStatus.HasValue)
            query = query.Where(d => d.DeviceStatus == input.DeviceStatus.Value);

        return await query.ToListAsync();
    }

    /// <summary>
    /// 新增设备
    /// </summary>
    [ApiDescriptionSettings(Name = "InsertDevice"), HttpPost]
    public async Task<long> InsertDevice([FromBody] DeviceCreateDto devic)
    {
        #region 唯一索引  

        Expression<Func<DeviceMaintenanceEntity, bool>> whereExpression = whereExp =>
                    whereExp.DeviceId.Equals(devic.DeviceId) && whereExp.DeviceId.Equals(devic.DeviceId);
        #endregion
        var isone = await CheckDeviceIdUnique(devic.DeviceId);
        var data = await _device.GetFirstAsync(whereExpression);
        if (data != null || !isone)
        {
            throw Oops.Oh("该记录已存在");
        }

        var entity = devic.Adapt<DeviceMaintenanceEntity>();

        // 填充实体的其他字段  
        entity.CreateUserId = _userinfo.UserId;
        entity.CreateUserName = _userinfo.RealName;
        entity.CreateOrgId = _userinfo.OrgId;
        entity.CreateTime = DateTime.Now;

        var Inventoryid = 0;


        return Inventoryid = await _device.AsInsertable(entity).ExecuteCommandAsync();

    }
    /// <summary>
    /// 校验设备ID是否唯一
    /// </summary>
    [ApiDescriptionSettings(Name = "CheckDeviceIdUnique"), HttpPost]
    public async Task<bool> CheckDeviceIdUnique([FromBody] string deviceId)
    {
        if (string.IsNullOrWhiteSpace(deviceId))
            throw new ArgumentException("设备ID不能为空", nameof(deviceId));

        // 查询数据库中是否存在相同的设备ID
        var existsInDb = await _device.AsQueryable().AnyAsync(d => d.DeviceId == deviceId);

        // 本地缓存或其他本地数据对比逻辑（示例）
        var existsInLocal = false; // 替换为实际的本地对比逻辑

        return !existsInDb && !existsInLocal;
    }
    /// <summary>
    /// 更新设备
    /// </summary>
    [ApiDescriptionSettings(Name = "UpdateDevice"), HttpPost]
    public async Task UpdateDevice([FromBody] DeviceUpdateDto entity)
    {

        #region 唯一索引  

        Expression<Func<DeviceMaintenanceEntity, bool>> whereExpression = whereExp =>
                    whereExp.DeviceId.Equals(entity.DeviceId) && whereExp.DeviceId.Equals(entity.DeviceId);
        #endregion
        var isone = await CheckDeviceIdUnique(entity.DeviceId);
        var data = await _device.GetFirstAsync(whereExpression);
        if (data != null || !isone)
        {
            data.UpdateTime = DateTime.Now;
            data.UpdateUserName = _userinfo.RealName;
            data.UpdateUserId = _userinfo.UserId;
            data.InOrOut = entity.InOrOut;
            data.DeviceId = entity.DeviceId;
            data.DeviceType = entity.DeviceType;
            data.Description = entity.Description;
            data.Storey = entity.Storey;
            data.DeviceStatus = entity.DeviceStatus;
        }


        // 将 DTO 转换为实体
        var dataentity = data.Adapt<DeviceMaintenanceEntity>();

        await _device.AsUpdateable(dataentity).ExecuteCommandAsync();
    }

    /// <summary>
    /// 删除设备
    /// </summary>
    [ApiDescriptionSettings(Name = "DeleteDevice"), HttpDelete]
    [DisplayName("删除设备")]
    public async Task DeleteDevice([FromBody] DeviceDeleteDto id)
    {
        #region "校验唯一索引"
        Expression<Func<DeviceMaintenanceEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(id);
        #endregion    
        var entity = await _device.GetFirstAsync(whereExpression);//?? throw Oops.Oh(ErrorCodeEnum.D1002);

        await _device.DeleteAsync(entity); // 假删除
                                           //await _rep.DeleteAsync(entity); // 真删除


    }

    /// <summary>
    /// 批量删除设备
    /// </summary>
    [ApiDescriptionSettings(Name = "BatchDeleteDevice"), HttpDelete]
    [DisplayName("批量删除设备")]
    public virtual async Task<int> BatchDeleteDevice([FromBody] List<DeviceDeleteDto> ids)
    {
        foreach (var item in ids)
        {
            #region "校验唯一索引"
            Expression<Func<DeviceMaintenanceEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(item.Id);
            #endregion
            var entity = await _device.GetFirstAsync(whereExpression) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
            if (entity == null)
            {
                throw Oops.Oh("该记录不存在");
            }
            //else
            //{
            //    return await _device.AsDeleteable(entity).ExecuteCommand();

            //}
        }

        var deleteEntity = ids.Adapt<List<DeviceMaintenanceEntity>>();
        return await _device.AsDeleteable()
          .Where(deleteEntity)
          .ExecuteCommandAsync();
    }

    /// <summary>
    /// 下载模版
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("下载模版")]
    [HttpGet]
    public virtual async Task<IActionResult> DownloadDeviceTemplate()
    {
        return await Task.Run(() =>
        {
            #region "校验"
            string fileName = "DeviceTemplate.xlsx";
            string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}/Template/{fileName}";
            if (!File.Exists(filePath))
            {
                throw Oops.Oh(10002, "找不到该模板：" + filePath);
            }
            #endregion

            var path = Path.Combine(filePath);
            return new FileStreamResult(new FileStream(path, FileMode.Open), System.Net.Mime.MediaTypeNames.Application.Octet)
            {
                FileDownloadName = fileName
            };
        });
    }
    /// <summary>
    /// 导出设备信息为 Excel
    /// </summary>
    [UnitOfWork]
    [DisplayName("导出设备为Excel")]
    [ApiDescriptionSettings(Name = "DeviceExportExcel"), HttpPost]
    public virtual async Task<IActionResult> DeviceExportExcel([FromBody] DevicePageInputDto input)
    {
        var list = await GetDeviceList(input);

        // 使用 NPOI 创建 Excel 文件
        var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
        var sheet = workbook.CreateSheet("设备信息");

        // 创建表头
        var headerRow = sheet.CreateRow(0);
        headerRow.CreateCell(0).SetCellValue("设备ID");
        headerRow.CreateCell(1).SetCellValue("设备类型");
        headerRow.CreateCell(2).SetCellValue("描述");
        headerRow.CreateCell(3).SetCellValue("层数");
        headerRow.CreateCell(4).SetCellValue("状态");
        headerRow.CreateCell(5).SetCellValue("出入口");

        // 填充数据
        for (int i = 0; i < list.Count; i++)
        {
            var row = sheet.CreateRow(i + 1);
            var device = list[i];
            row.CreateCell(0).SetCellValue(device.DeviceId);
            row.CreateCell(1).SetCellValue(device.DeviceType == 1 ? "提升机" : "AGV");
            row.CreateCell(2).SetCellValue(device.Description);
            row.CreateCell(3).SetCellValue(device.Storey.ToString());
            row.CreateCell(4).SetCellValue(device.DeviceStatus == 1 ? "故障" : "可用");
            row.CreateCell(5).SetCellValue(device.InOrOut == 1 ? "出口" : "入口");
        }

        // 将 Excel 文件写入内存流
        using var memoryStream = new MemoryStream();
        workbook.Write(memoryStream);
        var bytes = memoryStream.ToArray();

        // 返回文件结果
        return new FileContentResult(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
        {
            FileDownloadName = "DeviceExport.xlsx"
        };
    }


    /// <summary>
    /// 导地图维护
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>

    [UnitOfWork]
    [DisplayName("导入设备")]
    [ApiDescriptionSettings(Name = "ImportDevice"), HttpPost]
    public virtual async Task<List<ImportDeviceOutput>> ImportDevice([Required] IFormFile file)
    {

        if (file != null)
        {
            var fileDir = AppDomain.CurrentDomain.BaseDirectory + @"ImportFile";
            if (!Directory.Exists(fileDir))

            {
                Directory.CreateDirectory(fileDir);
            }
            //文件名称
            string fileName = file.FileName;
            //文件类型
            string fileType = file.FileName.Substring(fileName.LastIndexOf("."));
            //上传的文件的路径
            string filePath = fileDir + $@"/{fileName}";
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                file.CopyTo(fs);
            }

            if (fileType == ".xlsx" || fileType == ".xls")
            {
                ExcelHelper eh = new ExcelHelper(filePath);
                DataTable dt = eh.ExcelToDataTable("", true);
                eh.Dispose();
                if (dt == null || dt.Rows.Count == 0)
                {
                    throw Oops.Oh("文件为空！");
                }


                #region "校验模板字段"
                if (!dt.Columns.Contains("设备ID") || !dt.Columns.Contains("设备类型") || !dt.Columns.Contains("描述") || !dt.Columns.Contains("层数") || !dt.Columns.Contains("状态") || !dt.Columns.Contains("出入口"))
                {
                    throw Oops.Oh("文件模板错误！请重新下载模板");
                }
                var orderid = string.Empty;

                //不存在订单编号自己生成
                // orderid = await GenerateOrderIdAsync();

                #endregion

                List<ImportDeviceOutput> listLoad = new List<ImportDeviceOutput>();
                int i = 0;
                foreach (DataRow row in dt.Rows)
                {
                    i++;
                    //校验关联信息
                    ImportDeviceOutput orderInfoEntity = new ImportDeviceOutput
                    {
                        DeviceId = row["设备ID"].GetCString(),
                        DeviceType = row["设备类型"].ToString() == "AGV" ? 0 : 1,
                        Description = row["描述"].GetCString(),
                        Storey = row["层数"].GetCInt(),
                        DeviceStatus = row["状态"].GetCString()=="可用"?0:1,
                        InOrOut = row["出入口"].GetCString()=="入库口" ? 0 : 1,

                    };
                    #region "校验必填项"

                    #endregion
                    //用唯一索引查询非重复
                    Expression<Func<DeviceMaintenanceEntity, bool>> whereExpression = whereExp =>
                        whereExp.DeviceId.Equals(orderInfoEntity.DeviceId);
                    var data = await _device.GetFirstAsync(whereExpression);
                    if (data == null)
                    {
                        #region "自定义校验"

                        orderInfoEntity.CreateUserId = _userinfo.UserId;
                        orderInfoEntity.CreateTime = DateTime.Now;
                        orderInfoEntity.CreateOrgId = _userinfo.OrgId;
                        orderInfoEntity.CreateUserId = _userinfo.UserId;
                        orderInfoEntity.CreateUserName = _userinfo.RealName;

                        data = _device.Adapt(orderInfoEntity);
                        #endregion

                        var rtAdd = await _device.AsInsertable(data).ExecuteCommandAsync();
                        if (rtAdd != 1)
                        {
                            orderInfoEntity.ResultCode = 10004;
                            orderInfoEntity.Message = "插入失败";
                        }
                    }
                    else
                    {
                        #region "自定义校验"  

                        data.UpdateUserId = _userinfo.UserId;
                        data.UpdateTime = DateTime.Now;
                        data.UpdateUserName = _userinfo.RealName;
                        data.DeviceStatus = orderInfoEntity.DeviceStatus;
                        data.DeviceId = orderInfoEntity.DeviceId;
                        data.DeviceType = orderInfoEntity.DeviceType;
                        data.Description = orderInfoEntity.Description;
                        data.Storey = orderInfoEntity.Storey;
                        data.InOrOut = orderInfoEntity.InOrOut;
                        // 使用 Mapster 的 Adapt 方法将 orderInfoEntity 的值替换到 data 中  

                        //不能用Adapt替换因为importPosition中没主键

                        var order = data.Adapt(orderInfoEntity);
                        #endregion
                        var rtUpdate = await _device.AsUpdateable(order).ExecuteCommandAsync();
                        if (rtUpdate != 1)
                        {
                            orderInfoEntity.ResultCode = 10004;
                            orderInfoEntity.Message = "更新失败";
                        }
                    }

                    if (orderInfoEntity.ResultCode != 200)
                        listLoad.Add(orderInfoEntity);
                }

                // 返回导入失败数据
                if (listLoad.Count > 0)
                {
                    return listLoad;
                }
            }
            else
            {
                throw Oops.Oh(10002, "文件内容为空！");
            }
        }
        else
        {
            throw Oops.Oh(10002, "请选择文件！");
        }
        return null;
    }

}




